// 采样率
const sampleRate = 16000;
// 通道数
const channels = 1;
// 频率
const frequency = 1024;

/**
 *  创建切片录制对象
 */
const recordFunc = () => {
  const record = document.getElementById("record");
  const stop = document.getElementById("stop");

  // 创建一个新的AudioContext并设置采样率
  if (navigator.mediaDevices) {
    const constraints = { audio: true };
    navigator.mediaDevices
      .getUserMedia(constraints)
      .then((stream) => {
        const audioContext = new AudioContext({ sampleRate: sampleRate });
        const source = audioContext.createMediaStreamSource(stream);
        const processor = audioContext.createScriptProcessor(1024, 1, 1);

        let audioChunks = [];
        processor.onaudioprocess = (e) => {
          const inputData = e.inputBuffer.getChannelData(0);
          audioChunks.push(new Float32Array(inputData));
        };

        source.connect(processor);
        processor.connect(audioContext.destination);

        const mediaRecorder = new MediaRecorder(stream);

        record.onclick = () => {
          audioChunks = [];
          mediaRecorder.start();
          console.log(mediaRecorder.state);
          console.log("recorder started");
          record.style.background = "red";
          record.style.color = "black";
        };

        stop.onclick = () => {
          mediaRecorder.stop();
          console.log(mediaRecorder.state);
          console.log("recorder stopped");
          record.style.background = "";
          record.style.color = "";
        };

        mediaRecorder.onstop = (e) => {
          console.log("data available after MediaRecorder.stop() called.");

          const clipName = prompt("Enter a name for your sound clip");

          const clipContainer = document.createElement("article");
          const clipLabel = document.createElement("p");
          const audio = document.createElement("audio");
          const deleteButton = document.createElement("button");
          const mainContainer = document.querySelector("body");

          clipContainer.classList.add("clip");
          audio.setAttribute("controls", "");
          deleteButton.textContent = "Delete";
          clipLabel.textContent = clipName;

          clipContainer.appendChild(audio);
          clipContainer.appendChild(clipLabel);
          clipContainer.appendChild(deleteButton);
          mainContainer.appendChild(clipContainer);

          const wavBlob = createWavBlob(audioChunks, sampleRate, channels);
          const audioURL = URL.createObjectURL(wavBlob);
          audio.src = audioURL;
          console.log("recorder stopped");

          deleteButton.onclick = (e) => {
            const evtTgt = e.target;
            evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
          };
        };

        mediaRecorder.ondataavailable = (e) => {
          // This event is not used for WAV recording
        };
      })
      .catch((err) => {
        console.error(`The following error occurred: ${err}`);
      });
  }
};

function createWavBlob(audioChunks, sampleRate, channels) {
  const numSamples = audioChunks.reduce((acc, chunk) => acc + chunk.length, 0);
  const buffer = new ArrayBuffer(44 + numSamples * 2);
  const view = new DataView(buffer);

  // Write WAV header
  writeString(view, 0, "RIFF");
  view.setUint32(4, 36 + numSamples * 2, true);
  writeString(view, 8, "WAVE");
  writeString(view, 12, "fmt ");
  view.setUint32(16, 16, true);
  view.setUint16(20, 1, true);
  view.setUint16(22, channels, true);
  view.setUint32(24, sampleRate, true);
  view.setUint32(28, sampleRate * 2, true);
  view.setUint16(32, 2, true);
  view.setUint16(34, 16, true);
  writeString(view, 36, "data");
  view.setUint32(40, numSamples * 2, true);

  // Write audio data
  let offset = 44;
  for (const chunk of audioChunks) {
    for (let i = 0; i < chunk.length; i++) {
      view.setInt16(offset, chunk[i] * 32767, true);
      offset += 2;
    }
  }

  return new Blob([buffer], { type: "audio/wav" });
}

function writeString(view, offset, string) {
  for (let i = 0; i < string.length; i++) {
    view.setUint8(offset + i, string.charCodeAt(i));
  }
}
